

package tomkitty;

import java.io.*;
import java.net.*;
import java.util.*;

/**
 *
 * <code>ConnectionHandler</code> takes care of handling requests for the 
 * <code>Server</code> class. The http header is examined and the requested 
 * resource is returned, if
 * possible. If the resource is the name of a turdlet, then a turdlet of
 * that type is instantiated and connected to the input and output buffers,
 * and all IO is then handled by the turdlet. Otherwise, if no turdlet can
 * be found to correspond with the resource name or if an exception is
 * thrown somewhere, an <code>ErrorTurdlet</code> will be instantiated 
 * to return an
 * appropriate response. Currently only the GET and HEAD HTTP methods are
 * implemented, but POST will be included eventually.
 *
 * @author alan
 * @author micha
 */
public class TkConnectionHandler extends Turdlet 
  implements Runnable, ConnectionHandler {

  private boolean master = true;
  private ConnectionHandlerPool pool = null;
  private Configuration config = null;

  public TkConnectionHandler() {
  }

  public TkConnectionHandler(ConnectionHandlerPool pool) {
    this.master = false;
    this.pool = pool;
  }

  public Handler init(Handler handler, AppContext context) {
    super.init(handler, context);

    this.config = context.getConfig();
    if (master) {
      int min = Integer.valueOf(config.get(CONF_MINTHREADS)).intValue();
      int max = Integer.valueOf(config.get(CONF_MAXTHREADS)).intValue();
      pool = new TkConnectionHandlerPool(handler, context, min, max);
    } else {
      (new Thread(this)).start();
    }

    return this;
  }

  public void doit() {
  }

  public synchronized void handle(Request req, Response resp) {
    if (!master) {
      this.request = req;
      this.response = resp;
      notify();
    } else {
      try {
        pool.getConnectionHandler().handle(req, resp);
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
  }

  public synchronized void run() {

    while (true) {

      // wait until a request comes in

      try {
        if (request == null) {
          wait();
        }
      } catch(InterruptedException e) {
        e.printStackTrace();  
      }

      // socket is assigned. it will already be connected and ready.

      handler.handle(request, response);

      request = null;

      if (! master) {
        pool.recycle(this);
      }

    }

  }

}
